Skip to content

Commit

Permalink
in-copy-note
Browse files Browse the repository at this point in the history
  • Loading branch information
danakj committed Dec 23, 2024
1 parent b51e1ba commit db4b066
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 44 deletions.
33 changes: 23 additions & 10 deletions toolchain/check/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "llvm/ADT/STLExtras.h"
#include "toolchain/base/kind_switch.h"
#include "toolchain/check/context.h"
#include "toolchain/check/diagnostic_helpers.h"
#include "toolchain/check/operator.h"
#include "toolchain/check/pattern_match.h"
#include "toolchain/diagnostics/format_providers.h"
Expand Down Expand Up @@ -823,16 +824,28 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
{.type_id = foundation_type_id, .source_id = target.init_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,
});
if (foundation_value_id == SemIR::ErrorInst::SingletonInstId) {
return SemIR::ErrorInst::SingletonInstId;
{
// While the types are the same, the conversion can still fail if it
// performs a copy while converting the value to another category, and
// the type (or some part of it) is not copyable.
DiagnosticAnnotationScope 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,
});
if (foundation_value_id == SemIR::ErrorInst::SingletonInstId) {
return SemIR::ErrorInst::SingletonInstId;
}
}

return context.AddInst<SemIR::AsCompatible>(
Expand Down
39 changes: 21 additions & 18 deletions toolchain/check/testdata/as/fail_adapter_conversion.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,12 @@ fn F(a: A) {
// a copy to perform initialization. It's not clear whether that is the right
// behavior.

// CHECK:STDERR: fail_init_tuple.carbon:[[@LINE+4]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]
// CHECK:STDERR: fail_init_tuple.carbon:[[@LINE+7]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]
// CHECK:STDERR: var a_init: A = (a as (i32, Noncopyable)) as A;
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_init_tuple.carbon:[[@LINE+4]]:19: note: in copy of ``A`` [InCopy]
// CHECK:STDERR: var a_init: A = (a as (i32, Noncopyable)) as A;
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
var a_init: A = (a as (i32, Noncopyable)) as A;
}
Expand Down Expand Up @@ -297,23 +300,23 @@ var b: B = {.x = 1} as B;
// CHECK:STDOUT: %a_value: %A = bind_name a_value, %.loc13_46.2
// CHECK:STDOUT: %a_init.var: ref %A = var a_init
// CHECK:STDOUT: %a_init: ref %A = bind_name a_init, %a_init.var
// CHECK:STDOUT: %a.ref.loc24: %A = name_ref a, %a
// CHECK:STDOUT: %int_32.loc24: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc24: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: %Noncopyable.ref.loc24: type = name_ref Noncopyable, file.%Noncopyable.decl [template = constants.%Noncopyable]
// CHECK:STDOUT: %.loc24_42.1: %tuple.type.1 = tuple_literal (%i32.loc24, %Noncopyable.ref.loc24)
// CHECK:STDOUT: %.loc24_42.2: type = converted %.loc24_42.1, constants.%tuple.type.2 [template = constants.%tuple.type.2]
// CHECK:STDOUT: %.loc24_22.1: %tuple.type.2 = as_compatible %a.ref.loc24
// CHECK:STDOUT: %.loc24_22.2: %tuple.type.2 = converted %a.ref.loc24, %.loc24_22.1
// CHECK:STDOUT: %A.ref.loc24: type = name_ref A, file.%A.decl [template = constants.%A]
// CHECK:STDOUT: %.loc24_45.1: %A = as_compatible %.loc24_22.2
// CHECK:STDOUT: %.loc24_45.2: %A = converted %.loc24_22.2, %.loc24_45.1
// CHECK:STDOUT: %.loc24_49.1: %tuple.type.2 = as_compatible %.loc24_45.2
// CHECK:STDOUT: %tuple.elem0.loc24_49.1: %i32 = tuple_access %.loc24_49.1, element0
// CHECK:STDOUT: %.loc24_49.2: ref %tuple.type.2 = as_compatible %a_init.var
// CHECK:STDOUT: %tuple.elem0.loc24_49.2: ref %i32 = tuple_access %.loc24_49.2, element0
// CHECK:STDOUT: %.loc24_49.3: init %i32 = initialize_from %tuple.elem0.loc24_49.1 to %tuple.elem0.loc24_49.2
// CHECK:STDOUT: %tuple.elem1: %Noncopyable = tuple_access %.loc24_49.1, element1
// CHECK:STDOUT: %a.ref.loc27: %A = name_ref a, %a
// CHECK:STDOUT: %int_32.loc27: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc27: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: %Noncopyable.ref.loc27: type = name_ref Noncopyable, file.%Noncopyable.decl [template = constants.%Noncopyable]
// CHECK:STDOUT: %.loc27_42.1: %tuple.type.1 = tuple_literal (%i32.loc27, %Noncopyable.ref.loc27)
// CHECK:STDOUT: %.loc27_42.2: type = converted %.loc27_42.1, constants.%tuple.type.2 [template = constants.%tuple.type.2]
// CHECK:STDOUT: %.loc27_22.1: %tuple.type.2 = as_compatible %a.ref.loc27
// CHECK:STDOUT: %.loc27_22.2: %tuple.type.2 = converted %a.ref.loc27, %.loc27_22.1
// CHECK:STDOUT: %A.ref.loc27: type = name_ref A, file.%A.decl [template = constants.%A]
// CHECK:STDOUT: %.loc27_45.1: %A = as_compatible %.loc27_22.2
// CHECK:STDOUT: %.loc27_45.2: %A = converted %.loc27_22.2, %.loc27_45.1
// CHECK:STDOUT: %.loc27_49.1: %tuple.type.2 = as_compatible %.loc27_45.2
// CHECK:STDOUT: %tuple.elem0.loc27_49.1: %i32 = tuple_access %.loc27_49.1, element0
// CHECK:STDOUT: %.loc27_49.2: ref %tuple.type.2 = as_compatible %a_init.var
// CHECK:STDOUT: %tuple.elem0.loc27_49.2: ref %i32 = tuple_access %.loc27_49.2, element0
// CHECK:STDOUT: %.loc27_49.3: init %i32 = initialize_from %tuple.elem0.loc27_49.1 to %tuple.elem0.loc27_49.2
// CHECK:STDOUT: %tuple.elem1: %Noncopyable = tuple_access %.loc27_49.1, element1
// CHECK:STDOUT: assign %a_init.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
Expand Down
38 changes: 22 additions & 16 deletions toolchain/check/testdata/class/adapter/adapt_copy.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,20 @@ class AdaptNoncopyableIndirect {
}

fn H(a: AdaptNoncopyableIndirect) -> AdaptNoncopyableIndirect {
// CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+4]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]
// CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+7]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]
// CHECK:STDERR: var b: AdaptNoncopyableIndirect = a;
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+4]]:37: note: in copy of ``AdaptNoncopyableIndirect`` [InCopy]
// CHECK:STDERR: var b: AdaptNoncopyableIndirect = a;
// CHECK:STDERR: ^
// CHECK:STDERR:
var b: AdaptNoncopyableIndirect = a;
// CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+3]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]
// CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+6]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]
// CHECK:STDERR: return b;
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+3]]:10: note: in copy of ``AdaptNoncopyableIndirect`` [InCopy]
// CHECK:STDERR: return b;
// CHECK:STDERR: ^
return b;
}

Expand Down Expand Up @@ -557,22 +563,22 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
// CHECK:STDOUT: %b.var: ref %AdaptNoncopyableIndirect = var b
// CHECK:STDOUT: %b: ref %AdaptNoncopyableIndirect = bind_name b, %b.var
// CHECK:STDOUT: %a.ref: %AdaptNoncopyableIndirect = name_ref a, %a
// CHECK:STDOUT: %.loc17_38.1: %tuple.type.2 = as_compatible %a.ref
// CHECK:STDOUT: %tuple.elem0.loc17_38.1: %i32 = tuple_access %.loc17_38.1, element0
// CHECK:STDOUT: %.loc17_38.2: ref %tuple.type.2 = as_compatible %b.var
// CHECK:STDOUT: %tuple.elem0.loc17_38.2: ref %i32 = tuple_access %.loc17_38.2, element0
// CHECK:STDOUT: %.loc17_38.3: init %i32 = initialize_from %tuple.elem0.loc17_38.1 to %tuple.elem0.loc17_38.2
// CHECK:STDOUT: %tuple.elem1.loc17: %Noncopyable = tuple_access %.loc17_38.1, element1
// CHECK:STDOUT: %.loc20_38.1: %tuple.type.2 = as_compatible %a.ref
// CHECK:STDOUT: %tuple.elem0.loc20_38.1: %i32 = tuple_access %.loc20_38.1, element0
// CHECK:STDOUT: %.loc20_38.2: ref %tuple.type.2 = as_compatible %b.var
// CHECK:STDOUT: %tuple.elem0.loc20_38.2: ref %i32 = tuple_access %.loc20_38.2, element0
// CHECK:STDOUT: %.loc20_38.3: init %i32 = initialize_from %tuple.elem0.loc20_38.1 to %tuple.elem0.loc20_38.2
// CHECK:STDOUT: %tuple.elem1.loc20: %Noncopyable = tuple_access %.loc20_38.1, element1
// CHECK:STDOUT: assign %b.var, <error>
// CHECK:STDOUT: %b.ref: ref %AdaptNoncopyableIndirect = name_ref b, %b
// CHECK:STDOUT: %.loc21_11.1: ref %tuple.type.2 = as_compatible %b.ref
// CHECK:STDOUT: %tuple.elem0.loc21_11.1: ref %i32 = tuple_access %.loc21_11.1, element0
// CHECK:STDOUT: %.loc21_11.2: %i32 = bind_value %tuple.elem0.loc21_11.1
// CHECK:STDOUT: %.loc21_11.3: ref %tuple.type.2 = as_compatible %return
// CHECK:STDOUT: %tuple.elem0.loc21_11.2: ref %i32 = tuple_access %.loc21_11.3, element0
// CHECK:STDOUT: %.loc21_11.4: init %i32 = initialize_from %.loc21_11.2 to %tuple.elem0.loc21_11.2
// CHECK:STDOUT: %tuple.elem1.loc21: ref %Noncopyable = tuple_access %.loc21_11.1, element1
// CHECK:STDOUT: %.loc21_11.5: %Noncopyable = bind_value %tuple.elem1.loc21
// CHECK:STDOUT: %.loc27_11.1: ref %tuple.type.2 = as_compatible %b.ref
// CHECK:STDOUT: %tuple.elem0.loc27_11.1: ref %i32 = tuple_access %.loc27_11.1, element0
// CHECK:STDOUT: %.loc27_11.2: %i32 = bind_value %tuple.elem0.loc27_11.1
// CHECK:STDOUT: %.loc27_11.3: ref %tuple.type.2 = as_compatible %return
// CHECK:STDOUT: %tuple.elem0.loc27_11.2: ref %i32 = tuple_access %.loc27_11.3, element0
// CHECK:STDOUT: %.loc27_11.4: init %i32 = initialize_from %.loc27_11.2 to %tuple.elem0.loc27_11.2
// CHECK:STDOUT: %tuple.elem1.loc27: ref %Noncopyable = tuple_access %.loc27_11.1, element1
// CHECK:STDOUT: %.loc27_11.5: %Noncopyable = bind_value %tuple.elem1.loc27
// CHECK:STDOUT: return <error> to %return
// CHECK:STDOUT: }
// CHECK:STDOUT:
Expand Down
1 change: 1 addition & 0 deletions toolchain/diagnostics/diagnostic_kind.def
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ CARBON_DIAGNOSTIC_KIND(IncompleteTypeInLetDecl)
CARBON_DIAGNOSTIC_KIND(IncompleteTypeInMemberAccess)
CARBON_DIAGNOSTIC_KIND(IncompleteTypeInValueConversion)
CARBON_DIAGNOSTIC_KIND(IncompleteTypeInVarDecl)
CARBON_DIAGNOSTIC_KIND(InCopy)
CARBON_DIAGNOSTIC_KIND(IntTooLargeForType)
CARBON_DIAGNOSTIC_KIND(IntWidthNotMultipleOf8)
CARBON_DIAGNOSTIC_KIND(IntWidthNotPositive)
Expand Down

0 comments on commit db4b066

Please sign in to comment.