Repository: carbon-language/carbon-lang
File: toolchain/check/convert.cpp (C++)

Code before:
        // the type (or some part of it) is not copyable.
        Diagnostics::AnnotationScope annotate_diagnostics(
            &context.emitter(), [&](auto& builder) {
              CARBON_DIAGNOSTIC(InCopy, Note, "in copy of {0}", TypeOfInstId);
              builder.Note(value_id, InCopy, value_id);
            });

        foundation_value_id =
            PerformBuiltinConversion(context, loc_id, foundation_value_id,
                                     {.kind = target.kind,
                                      .type_id = foundation_type_id,
                                      .init_id = foundation_init_id,
                                      .init_block = target.init_block,
                                      .diagnose = target.diagnose});
        if (foundation_value_id == SemIR::ErrorInst::InstId) {
          return SemIR::ErrorInst::InstId;
        }
      }

      return AddInst<SemIR::AsCompatible>(
          context, loc_id,
          {.type_id = target.type_id, .source_id = foundation_value_id});
    }
  }

  // T implicitly converts to U if T and U are the same ignorig qualifiers, and
  // we're allowed to remove / add any qualifiers that differ. Similarly, T
  // explicitly converts to U if T is compatible with U, and we're allowed to
  // remove / add any qualifiers that differ.
  if (target.type_id != value_type_id) {
    auto [target_foundation_id, target_quals] =
        target.is_explicit_as()
            ? context.types().GetTransitiveUnqualifiedAdaptedType(
                  target.type_id)
            : context.types().GetUnqualifiedTypeAndQualifiers(target.type_id);
    auto [value_foundation_id, value_quals] =
        target.is_explicit_as()
            ? context.types().GetTransitiveUnqualifiedAdaptedType(value_type_id)
            : context.types().GetUnqualifiedTypeAndQualifiers(value_type_id);
    if (target_foundation_id == value_foundation_id) {
      auto category = SemIR::GetExprCategory(context.sem_ir(), value_id);
      auto added_quals = target_quals & ~value_quals;
      auto removed_quals = value_quals & ~target_quals;
      if (CanAddQualifiers(added_quals, category) &&
          CanRemoveQualifiers(removed_quals, category, target.kind)) {
        // For a struct or tuple literal, perform a category conversion if
        // necessary.
        if (category == SemIR::ExprCategory::Mixed) {
          value_id = PerformBuiltinConversion(context, loc_id, value_id,
                                              {.kind = ConversionTarget::Value,
                                               .type_id = value_type_id,

Review comment (suggestion):
```suggestion
  // T implicitly converts to U if T and U are the same ignoring qualifiers, and
```

Code after:
        // the type (or some part of it) is not copyable.
        Diagnostics::AnnotationScope annotate_diagnostics(
            &context.emitter(), [&](auto& builder) {
              CARBON_DIAGNOSTIC(InCopy, Note, "in copy of {0}", TypeOfInstId);
              builder.Note(value_id, InCopy, value_id);
            });

        foundation_value_id =
            PerformBuiltinConversion(context, loc_id, foundation_value_id,
                                     {.kind = target.kind,
                                      .type_id = foundation_type_id,
                                      .init_id = foundation_init_id,
                                      .init_block = target.init_block,
                                      .diagnose = target.diagnose});
        if (foundation_value_id == SemIR::ErrorInst::InstId) {
          return SemIR::ErrorInst::InstId;
        }
      }

      return AddInst<SemIR::AsCompatible>(
          context, loc_id,
          {.type_id = target.type_id, .source_id = foundation_value_id});
    }
  }

  // T implicitly converts to U if T and U are the same ignoring qualifiers, and
  // we're allowed to remove / add any qualifiers that differ. Similarly, T
  // explicitly converts to U if T is compatible with U, and we're allowed to
  // remove / add any qualifiers that differ.
  if (target.type_id != value_type_id) {
    auto [target_foundation_id, target_quals] =
        target.is_explicit_as()
            ? context.types().GetTransitiveUnqualifiedAdaptedType(
                  target.type_id)
            : context.types().GetUnqualifiedTypeAndQualifiers(target.type_id);
    auto [value_foundation_id, value_quals] =
        target.is_explicit_as()
            ? context.types().GetTransitiveUnqualifiedAdaptedType(value_type_id)
            : context.types().GetUnqualifiedTypeAndQualifiers(value_type_id);
    if (target_foundation_id == value_foundation_id) {
      auto category = SemIR::GetExprCategory(context.sem_ir(), value_id);
      auto added_quals = target_quals & ~value_quals;
      auto removed_quals = value_quals & ~target_quals;
      if (CanAddQualifiers(added_quals, category) &&
          CanRemoveQualifiers(removed_quals, category, target.kind)) {
        // For a struct or tuple literal, perform a category conversion if
        // necessary.
        if (category == SemIR::ExprCategory::Mixed) {
          value_id = PerformBuiltinConversion(context, loc_id, value_id,
                                              {.kind = ConversionTarget::Value,
                                               .type_id = value_type_id,