diff --git a/toolchain/check/handle_literal.cpp b/toolchain/check/handle_literal.cpp index 590fb9b59b0f..11536140cd5a 100644 --- a/toolchain/check/handle_literal.cpp +++ b/toolchain/check/handle_literal.cpp @@ -83,6 +83,13 @@ auto HandleParseNode(Context& context, Parse::BoolTypeLiteralId node_id) return true; } +auto HandleParseNode(Context& context, Parse::CharTypeLiteralId node_id) + -> bool { + auto type_inst_id = MakeCharTypeLiteral(context, node_id); + context.node_stack().Push(node_id, type_inst_id); + return true; +} + // Shared implementation for handling `iN` and `uN` literals. static auto HandleIntOrUnsignedIntTypeLiteral(Context& context, Parse::NodeId node_id, diff --git a/toolchain/check/testdata/function/call/fail_not_callable.carbon b/toolchain/check/testdata/function/call/fail_not_callable.carbon index bf65249fddd4..d4cd2a397a8a 100644 --- a/toolchain/check/testdata/function/call/fail_not_callable.carbon +++ b/toolchain/check/testdata/function/call/fail_not_callable.carbon @@ -11,7 +11,7 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/fail_not_callable.carbon fn Run() { - // CHECK:STDERR: fail_not_callable.carbon:[[@LINE+4]]:16: error: value of type `Core.String` is not callable [CallToNonCallable] + // CHECK:STDERR: fail_not_callable.carbon:[[@LINE+4]]:16: error: value of type `str` is not callable [CallToNonCallable] // CHECK:STDERR: var x: i32 = "hello"(); // CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon index 23dcd2064617..9d1379ae6c4a 100644 --- a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon +++ b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon @@ -1006,12 +1006,12 @@ fn F() { // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %.d16: Core.CharLiteral = char_value U+0058 [concrete] -// CHECK:STDOUT: %Char: type = class_type @Char [concrete] -// CHECK:STDOUT: %ptr.fb0: type = ptr_type %Char [concrete] +// CHECK:STDOUT: %char: type = class_type @Char [concrete] +// CHECK:STDOUT: %ptr.fb0: type = ptr_type %char [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] // CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] -// CHECK:STDOUT: %ImplicitAs.type.3be: type = facet_type <@ImplicitAs, @ImplicitAs(%Char)> [concrete] -// CHECK:STDOUT: %ImplicitAs.Convert.type.f57: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%Char) [concrete] +// CHECK:STDOUT: %ImplicitAs.type.3be: type = facet_type <@ImplicitAs, @ImplicitAs(%char)> [concrete] +// CHECK:STDOUT: %ImplicitAs.Convert.type.f57: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%char) [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %ImplicitAs.impl_witness.892: = impl_witness imports.%ImplicitAs.impl_witness_table.1f2 [concrete] @@ -1020,15 +1020,15 @@ fn F() { // CHECK:STDOUT: %Core.CharLiteral.as.ImplicitAs.impl.Convert.type: type = fn_type @Core.CharLiteral.as.ImplicitAs.impl.Convert [concrete] // CHECK:STDOUT: %Core.CharLiteral.as.ImplicitAs.impl.Convert: %Core.CharLiteral.as.ImplicitAs.impl.Convert.type = struct_value () [concrete] // CHECK:STDOUT: %Core.CharLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %.d16, %Core.CharLiteral.as.ImplicitAs.impl.Convert [concrete] -// CHECK:STDOUT: %int_88: %Char = int_value 88 [concrete] +// CHECK:STDOUT: %int_88: %char = int_value 88 [concrete] // CHECK:STDOUT: %Copy.impl_witness.9ba: = impl_witness imports.%Copy.impl_witness_table.0e0 [concrete] -// CHECK:STDOUT: %Copy.facet.3d0: %Copy.type = facet_value %Char, (%Copy.impl_witness.9ba) [concrete] +// CHECK:STDOUT: %Copy.facet.3d0: %Copy.type = facet_value %char, (%Copy.impl_witness.9ba) [concrete] // CHECK:STDOUT: %.1ed: type = fn_type_with_self_type %Copy.Op.type, %Copy.facet.3d0 [concrete] -// CHECK:STDOUT: %Char.as.Copy.impl.Op.type: type = fn_type @Char.as.Copy.impl.Op [concrete] -// CHECK:STDOUT: %Char.as.Copy.impl.Op: %Char.as.Copy.impl.Op.type = struct_value () [concrete] -// CHECK:STDOUT: %Char.as.Copy.impl.Op.bound: = bound_method %int_88, %Char.as.Copy.impl.Op [concrete] -// CHECK:STDOUT: %Char.as.Destroy.impl.Op.type: type = fn_type @Char.as.Destroy.impl.Op [concrete] -// CHECK:STDOUT: %Char.as.Destroy.impl.Op: %Char.as.Destroy.impl.Op.type = struct_value () [concrete] +// CHECK:STDOUT: %char.as.Copy.impl.Op.type: type = fn_type @char.as.Copy.impl.Op [concrete] +// CHECK:STDOUT: %char.as.Copy.impl.Op: %char.as.Copy.impl.Op.type = struct_value () [concrete] +// CHECK:STDOUT: %char.as.Copy.impl.Op.bound: = bound_method %int_88, %char.as.Copy.impl.Op [concrete] +// CHECK:STDOUT: %char.as.Destroy.impl.Op.type: type = fn_type @char.as.Destroy.impl.Op [concrete] +// CHECK:STDOUT: %char.as.Destroy.impl.Op: %char.as.Destroy.impl.Op.type = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -1044,8 +1044,8 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import_ref.543: %Core.CharLiteral.as.ImplicitAs.impl.Convert.type = import_ref Core//prelude/types/char, loc23_36, loaded [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.1f2 = impl_witness_table (%Core.import_ref.543), @Core.CharLiteral.as.ImplicitAs.impl [concrete] -// CHECK:STDOUT: %Core.import_ref.247: %Char.as.Copy.impl.Op.type = import_ref Core//prelude/types/char, loc19_31, loaded [concrete = constants.%Char.as.Copy.impl.Op] -// CHECK:STDOUT: %Copy.impl_witness_table.0e0 = impl_witness_table (%Core.import_ref.247), @Char.as.Copy.impl [concrete] +// CHECK:STDOUT: %Core.import_ref.247: %char.as.Copy.impl.Op.type = import_ref Core//prelude/types/char, loc19_31, loaded [concrete = constants.%char.as.Copy.impl.Op] +// CHECK:STDOUT: %Copy.impl_witness_table.0e0 = impl_witness_table (%Core.import_ref.247), @char.as.Copy.impl [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -1055,19 +1055,19 @@ fn F() { // CHECK:STDOUT: %.loc8_11.1: Core.CharLiteral = char_value U+0058 [concrete = constants.%.d16] // CHECK:STDOUT: %impl.elem0.loc8_11.1: %.8d6 = impl_witness_access constants.%ImplicitAs.impl_witness.892, element0 [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert] // CHECK:STDOUT: %bound_method.loc8_11.1: = bound_method %.loc8_11.1, %impl.elem0.loc8_11.1 [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert.bound] -// CHECK:STDOUT: %Core.CharLiteral.as.ImplicitAs.impl.Convert.call: init %Char = call %bound_method.loc8_11.1(%.loc8_11.1) [concrete = constants.%int_88] -// CHECK:STDOUT: %.loc8_11.2: %Char = value_of_initializer %Core.CharLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_88] -// CHECK:STDOUT: %.loc8_11.3: %Char = converted %.loc8_11.1, %.loc8_11.2 [concrete = constants.%int_88] -// CHECK:STDOUT: %.loc8_11.4: ref %Char = temporary_storage -// CHECK:STDOUT: %impl.elem0.loc8_11.2: %.1ed = impl_witness_access constants.%Copy.impl_witness.9ba, element0 [concrete = constants.%Char.as.Copy.impl.Op] -// CHECK:STDOUT: %bound_method.loc8_11.2: = bound_method %.loc8_11.3, %impl.elem0.loc8_11.2 [concrete = constants.%Char.as.Copy.impl.Op.bound] -// CHECK:STDOUT: %Char.as.Copy.impl.Op.call: init %Char = call %bound_method.loc8_11.2(%.loc8_11.3) [concrete = constants.%int_88] -// CHECK:STDOUT: %.loc8_11.5: ref %Char = temporary %.loc8_11.4, %Char.as.Copy.impl.Op.call +// CHECK:STDOUT: %Core.CharLiteral.as.ImplicitAs.impl.Convert.call: init %char = call %bound_method.loc8_11.1(%.loc8_11.1) [concrete = constants.%int_88] +// CHECK:STDOUT: %.loc8_11.2: %char = value_of_initializer %Core.CharLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_88] +// CHECK:STDOUT: %.loc8_11.3: %char = converted %.loc8_11.1, %.loc8_11.2 [concrete = constants.%int_88] +// CHECK:STDOUT: %.loc8_11.4: ref %char = temporary_storage +// CHECK:STDOUT: %impl.elem0.loc8_11.2: %.1ed = impl_witness_access constants.%Copy.impl_witness.9ba, element0 [concrete = constants.%char.as.Copy.impl.Op] +// CHECK:STDOUT: %bound_method.loc8_11.2: = bound_method %.loc8_11.3, %impl.elem0.loc8_11.2 [concrete = constants.%char.as.Copy.impl.Op.bound] +// CHECK:STDOUT: %char.as.Copy.impl.Op.call: init %char = call %bound_method.loc8_11.2(%.loc8_11.3) [concrete = constants.%int_88] +// CHECK:STDOUT: %.loc8_11.5: ref %char = temporary %.loc8_11.4, %char.as.Copy.impl.Op.call // CHECK:STDOUT: %addr.loc8_14: %ptr.fb0 = addr_of %.loc8_11.5 // CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_14) -// CHECK:STDOUT: %Char.as.Destroy.impl.Op.bound: = bound_method %.loc8_11.5, constants.%Char.as.Destroy.impl.Op +// CHECK:STDOUT: %char.as.Destroy.impl.Op.bound: = bound_method %.loc8_11.5, constants.%char.as.Destroy.impl.Op // CHECK:STDOUT: %addr.loc8_11: %ptr.fb0 = addr_of %.loc8_11.5 -// CHECK:STDOUT: %Char.as.Destroy.impl.Op.call: init %empty_tuple.type = call %Char.as.Destroy.impl.Op.bound(%addr.loc8_11) +// CHECK:STDOUT: %char.as.Destroy.impl.Op.call: init %empty_tuple.type = call %char.as.Destroy.impl.Op.bound(%addr.loc8_11) // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/function/operators.carbon b/toolchain/check/testdata/interop/cpp/function/operators.carbon index 81fc5591ce78..fe489dc719a9 100644 --- a/toolchain/check/testdata/interop/cpp/function/operators.carbon +++ b/toolchain/check/testdata/interop/cpp/function/operators.carbon @@ -327,7 +327,7 @@ import Cpp library "plus_with_string_view_conversion.h"; fn F() { let s1: str = "hello"; let s2: str = "world"; - // CHECK:STDERR: fail_todo_import_plus_with_string_view_conversion.carbon:[[@LINE+4]]:18: error: cannot access member of interface `Core.AddWith(Core.String)` in type `Core.String` that does not implement that interface [MissingImplInMemberAccess] + // CHECK:STDERR: fail_todo_import_plus_with_string_view_conversion.carbon:[[@LINE+4]]:18: error: cannot access member of interface `Core.AddWith(str)` in type `str` that does not implement that interface [MissingImplInMemberAccess] // CHECK:STDERR: let c: Cpp.C = s1 + s2; // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon b/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon index de0fddd05c53..a2468256a3e8 100644 --- a/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon +++ b/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon @@ -46,7 +46,7 @@ import Cpp library "string_view.h"; //@dump-sem-ir-begin fn F() { - // CHECK:STDERR: fail_todo_5891_import_multiple.carbon:[[@LINE+7]]:3: error: call argument of type `Core.String` is not supported [CppCallArgTypeNotSupported] + // CHECK:STDERR: fail_todo_5891_import_multiple.carbon:[[@LINE+7]]:3: error: call argument of type `str` is not supported [CppCallArgTypeNotSupported] // CHECK:STDERR: Cpp.Consume("hello"); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_todo_5891_import_multiple.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction] @@ -69,7 +69,7 @@ fn G() -> str { // CHECK:STDOUT: %F.type: type = fn_type @F [concrete] // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete] -// CHECK:STDOUT: %String: type = class_type @String [concrete] +// CHECK:STDOUT: %str.ee0: type = class_type @String [concrete] // CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete] // CHECK:STDOUT: %u64: type = class_type @UInt, @UInt(%int_64) [concrete] // CHECK:STDOUT: %int_8: Core.IntLiteral = int_value 8 [concrete] @@ -77,15 +77,15 @@ fn G() -> str { // CHECK:STDOUT: %ptr.3e8: type = ptr_type %u8 [concrete] // CHECK:STDOUT: %.fd2: type = cpp_overload_set_type @Produce [concrete] // CHECK:STDOUT: %empty_struct.c28: %.fd2 = struct_value () [concrete] -// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "hello" [concrete] +// CHECK:STDOUT: %str.3b1: %ptr.3e8 = string_literal "hello" [concrete] // CHECK:STDOUT: %int_5: %u64 = int_value 5 [concrete] -// CHECK:STDOUT: %String.val: %String = struct_value (%str, %int_5) [concrete] -// CHECK:STDOUT: %pattern_type.461: type = pattern_type %String [concrete] +// CHECK:STDOUT: %String.val: %str.ee0 = struct_value (%str.3b1, %int_5) [concrete] +// CHECK:STDOUT: %pattern_type.461: type = pattern_type %str.ee0 [concrete] // CHECK:STDOUT: %G.type: type = fn_type @G [concrete] // CHECK:STDOUT: %G: %G.type = struct_value () [concrete] // CHECK:STDOUT: %.a47: type = cpp_overload_set_type @Produce__carbon_thunk [concrete] // CHECK:STDOUT: %empty_struct.ab9: %.a47 = struct_value () [concrete] -// CHECK:STDOUT: %ptr.85f: type = ptr_type %String [concrete] +// CHECK:STDOUT: %ptr.85f: type = ptr_type %str.ee0 [concrete] // CHECK:STDOUT: %Produce__carbon_thunk.type: type = fn_type @Produce__carbon_thunk [concrete] // CHECK:STDOUT: %Produce__carbon_thunk: %Produce__carbon_thunk.type = struct_value () [concrete] // CHECK:STDOUT: } @@ -111,8 +111,8 @@ fn G() -> str { // CHECK:STDOUT: %return.patt: %pattern_type.461 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.461 = out_param_pattern %return.patt, call_param0 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %return.param: ref %String = out_param call_param0 -// CHECK:STDOUT: %return: ref %String = return_slot %return.param +// CHECK:STDOUT: %return.param: ref %str.ee0 = out_param call_param0 +// CHECK:STDOUT: %return: ref %str.ee0 = return_slot %return.param // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -120,20 +120,20 @@ fn G() -> str { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %Consume.ref: %.fd2 = name_ref Consume, imports.%.f17 [concrete = constants.%empty_struct.c28] -// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "hello" [concrete = constants.%str] +// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "hello" [concrete = constants.%str.3b1] // CHECK:STDOUT: %int_5: %u64 = int_value 5 [concrete = constants.%int_5] -// CHECK:STDOUT: %String.val: %String = struct_value (%str, %int_5) [concrete = constants.%String.val] +// CHECK:STDOUT: %String.val: %str.ee0 = struct_value (%str, %int_5) [concrete = constants.%String.val] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @G() -> %return.param: %String { +// CHECK:STDOUT: fn @G() -> %return.param: %str.ee0 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %Produce.ref: %.a47 = name_ref Produce, imports.%.5d1 [concrete = constants.%empty_struct.ab9] -// CHECK:STDOUT: %.loc20: ref %String = splice_block %return {} +// CHECK:STDOUT: %.loc20: ref %str.ee0 = splice_block %return {} // CHECK:STDOUT: %addr: %ptr.85f = addr_of %.loc20 // CHECK:STDOUT: %Produce__carbon_thunk.call: init %empty_tuple.type = call imports.%Produce__carbon_thunk.decl(%addr) -// CHECK:STDOUT: %.loc21: init %String = in_place_init %Produce__carbon_thunk.call, %.loc20 +// CHECK:STDOUT: %.loc21: init %str.ee0 = in_place_init %Produce__carbon_thunk.call, %.loc20 // CHECK:STDOUT: return %.loc21 to %return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/primitives/import_symbolic.carbon b/toolchain/check/testdata/primitives/import_symbolic.carbon index 8e8c9fd8a251..e4e2fa3cf441 100644 --- a/toolchain/check/testdata/primitives/import_symbolic.carbon +++ b/toolchain/check/testdata/primitives/import_symbolic.carbon @@ -245,10 +245,10 @@ fn F() -> u32 { // CHECK:STDOUT: --- import_char.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %Char: type = class_type @Char [concrete] +// CHECK:STDOUT: %char: type = class_type @Char [concrete] // CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] -// CHECK:STDOUT: %int_97: %Char = int_value 97 [concrete] +// CHECK:STDOUT: %int_97: %char = int_value 97 [concrete] // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] @@ -256,26 +256,26 @@ fn F() -> u32 { // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %Copy.impl_witness.9ba: = impl_witness imports.%Copy.impl_witness_table.0e0 [concrete] -// CHECK:STDOUT: %Copy.facet.3d0: %Copy.type = facet_value %Char, (%Copy.impl_witness.9ba) [concrete] +// CHECK:STDOUT: %Copy.facet.3d0: %Copy.type = facet_value %char, (%Copy.impl_witness.9ba) [concrete] // CHECK:STDOUT: %.1ed: type = fn_type_with_self_type %Copy.Op.type, %Copy.facet.3d0 [concrete] -// CHECK:STDOUT: %Char.as.Copy.impl.Op.type: type = fn_type @Char.as.Copy.impl.Op [concrete] -// CHECK:STDOUT: %Char.as.Copy.impl.Op: %Char.as.Copy.impl.Op.type = struct_value () [concrete] -// CHECK:STDOUT: %Char.as.Copy.impl.Op.bound: = bound_method %int_97, %Char.as.Copy.impl.Op [concrete] +// CHECK:STDOUT: %char.as.Copy.impl.Op.type: type = fn_type @char.as.Copy.impl.Op [concrete] +// CHECK:STDOUT: %char.as.Copy.impl.Op: %char.as.Copy.impl.Op.type = struct_value () [concrete] +// CHECK:STDOUT: %char.as.Copy.impl.Op.bound: = bound_method %int_97, %char.as.Copy.impl.Op [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//char, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//char, C, loaded [concrete = constants.%C] // CHECK:STDOUT: %Main.import_ref.da1: %I.assoc_type = import_ref Main//char, loc5_10, loaded [concrete = constants.%assoc0.941] -// CHECK:STDOUT: %Main.import_ref.d0c: %Char = import_ref Main//char, loc10_30, loaded [concrete = constants.%int_97] +// CHECK:STDOUT: %Main.import_ref.d0c: %char = import_ref Main//char, loc10_30, loaded [concrete = constants.%int_97] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.d0c), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.8e8: %Char = import_ref Main//char, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: %Char = assoc_const_decl @val [concrete] {} -// CHECK:STDOUT: %Core.import_ref.247: %Char.as.Copy.impl.Op.type = import_ref Core//prelude/types/char, loc19_31, loaded [concrete = constants.%Char.as.Copy.impl.Op] -// CHECK:STDOUT: %Copy.impl_witness_table.0e0 = impl_witness_table (%Core.import_ref.247), @Char.as.Copy.impl [concrete] +// CHECK:STDOUT: %Main.import_ref.8e8: %char = import_ref Main//char, loc5_10, loaded [concrete = %val] +// CHECK:STDOUT: %val: %char = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Core.import_ref.247: %char.as.Copy.impl.Op.type = import_ref Core//prelude/types/char, loc19_31, loaded [concrete = constants.%char.as.Copy.impl.Op] +// CHECK:STDOUT: %Copy.impl_witness_table.0e0 = impl_witness_table (%Core.import_ref.247), @char.as.Copy.impl [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F() -> %Char { +// CHECK:STDOUT: fn @F() -> %char { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C] // CHECK:STDOUT: %I.ref: type = name_ref I, imports.%Main.I [concrete = constants.%I.type] @@ -284,11 +284,11 @@ fn F() -> u32 { // CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.da1 [concrete = constants.%assoc0.941] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %impl.elem0.loc7_18.1: %Char = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%int_97] -// CHECK:STDOUT: %impl.elem0.loc7_18.2: %.1ed = impl_witness_access constants.%Copy.impl_witness.9ba, element0 [concrete = constants.%Char.as.Copy.impl.Op] -// CHECK:STDOUT: %bound_method: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%Char.as.Copy.impl.Op.bound] -// CHECK:STDOUT: %Char.as.Copy.impl.Op.call: init %Char = call %bound_method(%impl.elem0.loc7_18.1) [concrete = constants.%int_97] -// CHECK:STDOUT: return %Char.as.Copy.impl.Op.call to %return +// CHECK:STDOUT: %impl.elem0.loc7_18.1: %char = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%int_97] +// CHECK:STDOUT: %impl.elem0.loc7_18.2: %.1ed = impl_witness_access constants.%Copy.impl_witness.9ba, element0 [concrete = constants.%char.as.Copy.impl.Op] +// CHECK:STDOUT: %bound_method: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%char.as.Copy.impl.Op.bound] +// CHECK:STDOUT: %char.as.Copy.impl.Op.call: init %char = call %bound_method(%impl.elem0.loc7_18.1) [concrete = constants.%int_97] +// CHECK:STDOUT: return %char.as.Copy.impl.Op.call to %return // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- import_char_literal.carbon diff --git a/toolchain/check/testdata/primitives/string_literals.carbon b/toolchain/check/testdata/primitives/string_literals.carbon index c6b885d5621b..f124719b42fb 100644 --- a/toolchain/check/testdata/primitives/string_literals.carbon +++ b/toolchain/check/testdata/primitives/string_literals.carbon @@ -37,7 +37,7 @@ class String { import Core library "unusual_string"; -// CHECK:STDERR: fail_use_unusual_string.carbon:[[@LINE+4]]:14: error: unexpected representation for type `Core.String` [StringLiteralTypeUnexpected] +// CHECK:STDERR: fail_use_unusual_string.carbon:[[@LINE+4]]:14: error: unexpected representation for type `str` [StringLiteralTypeUnexpected] // CHECK:STDERR: let x: str = "hello"; // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: @@ -116,14 +116,14 @@ This string contains 256 characters. Among them are: // CHECK:STDOUT: --- use_small_string.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %String: type = class_type @String [concrete] +// CHECK:STDOUT: %str.ee0: type = class_type @String [concrete] // CHECK:STDOUT: %int_8: Core.IntLiteral = int_value 8 [concrete] // CHECK:STDOUT: %u8: type = class_type @UInt, @UInt(%int_8) [concrete] // CHECK:STDOUT: %ptr.3e8: type = ptr_type %u8 [concrete] -// CHECK:STDOUT: %pattern_type.461: type = pattern_type %String [concrete] -// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "hello" [concrete] +// CHECK:STDOUT: %pattern_type.461: type = pattern_type %str.ee0 [concrete] +// CHECK:STDOUT: %str.3b1: %ptr.3e8 = string_literal "hello" [concrete] // CHECK:STDOUT: %int_5: %u8 = int_value 5 [concrete] -// CHECK:STDOUT: %String.val: %String = struct_value (%str, %int_5) [concrete] +// CHECK:STDOUT: %String.val: %str.ee0 = struct_value (%str.3b1, %int_5) [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -133,26 +133,26 @@ This string contains 256 characters. Among them are: // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %x.patt: %pattern_type.461 = binding_pattern x [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %x: %String = bind_name x, @__global_init.%String.val +// CHECK:STDOUT: %x: %str.ee0 = bind_name x, @__global_init.%String.val // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "hello" [concrete = constants.%str] +// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "hello" [concrete = constants.%str.3b1] // CHECK:STDOUT: %int_5: %u8 = int_value 5 [concrete = constants.%int_5] -// CHECK:STDOUT: %String.val: %String = struct_value (%str, %int_5) [concrete = constants.%String.val] +// CHECK:STDOUT: %String.val: %str.ee0 = struct_value (%str, %int_5) [concrete = constants.%String.val] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_overfill_small_string.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %String: type = class_type @String [concrete] +// CHECK:STDOUT: %str.ee0: type = class_type @String [concrete] // CHECK:STDOUT: %int_8: Core.IntLiteral = int_value 8 [concrete] // CHECK:STDOUT: %u8: type = class_type @UInt, @UInt(%int_8) [concrete] // CHECK:STDOUT: %ptr.3e8: type = ptr_type %u8 [concrete] -// CHECK:STDOUT: %pattern_type.461: type = pattern_type %String [concrete] -// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "A string so long its size does not fit in `u8`. This results in an error,\nbecause we can't form a `Core.String` value that describes this string.\n\nThis string contains 256 characters. Among them are:\n\n* 6 `g`s,\n* 21 `s`s,\n* 9 newlines,\n* and only one `p`.\n" [concrete] +// CHECK:STDOUT: %pattern_type.461: type = pattern_type %str.ee0 [concrete] +// CHECK:STDOUT: %str.294: %ptr.3e8 = string_literal "A string so long its size does not fit in `u8`. This results in an error,\nbecause we can't form a `Core.String` value that describes this string.\n\nThis string contains 256 characters. Among them are:\n\n* 6 `g`s,\n* 21 `s`s,\n* 9 newlines,\n* and only one `p`.\n" [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -162,12 +162,12 @@ This string contains 256 characters. Among them are: // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %x.patt: %pattern_type.461 = binding_pattern x [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %x: %String = bind_name x, [concrete = ] +// CHECK:STDOUT: %x: %str.ee0 = bind_name x, [concrete = ] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "A string so long its size does not fit in `u8`. This results in an error,\nbecause we can't form a `Core.String` value that describes this string.\n\nThis string contains 256 characters. Among them are:\n\n* 6 `g`s,\n* 21 `s`s,\n* 9 newlines,\n* and only one `p`.\n" [concrete = constants.%str] +// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "A string so long its size does not fit in `u8`. This results in an error,\nbecause we can't form a `Core.String` value that describes this string.\n\nThis string contains 256 characters. Among them are:\n\n* 6 `g`s,\n* 21 `s`s,\n* 9 newlines,\n* and only one `p`.\n" [concrete = constants.%str.294] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/primitives/type_literals.carbon b/toolchain/check/testdata/primitives/type_literals.carbon index 601adc08e97d..d4b88cbd2ed7 100644 --- a/toolchain/check/testdata/primitives/type_literals.carbon +++ b/toolchain/check/testdata/primitives/type_literals.carbon @@ -40,6 +40,14 @@ var test_f64: f64; var test_f128: f128; //@dump-sem-ir-end +// --- char.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let test_char: char = 'c'; +//@dump-sem-ir-end + // --- string.carbon library "[[@TEST_NAME]]"; @@ -201,6 +209,66 @@ library "[[@TEST_NAME]]"; // CHECK:STDERR: var x: type = 42; +// --- fail_stringify_type_literals.carbon + +library "[[@TEST_NAME]]"; + +// Ensure that type literals get stringified properly. + +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `()` to `i32` [ConversionFailure] +// CHECK:STDERR: var test_i32: i32 = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+4]]:1: note: type `()` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote] +// CHECK:STDERR: var test_i32: i32 = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +var test_i32: i32 = (); + +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `()` to `f32` [ConversionFailure] +// CHECK:STDERR: var test_f32: f32 = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+4]]:1: note: type `()` does not implement interface `Core.ImplicitAs(f32)` [MissingImplInMemberAccessNote] +// CHECK:STDERR: var test_f32: f32 = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +var test_f32: f32 = (); + +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `()` to `u32` [ConversionFailure] +// CHECK:STDERR: var test_u32: u32 = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+4]]:1: note: type `()` does not implement interface `Core.ImplicitAs(u32)` [MissingImplInMemberAccessNote] +// CHECK:STDERR: var test_u32: u32 = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +var test_u32: u32 = (); + +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `()` to `bool` [ConversionFailure] +// CHECK:STDERR: var test_bool: bool = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+4]]:1: note: type `()` does not implement interface `Core.ImplicitAs(bool)` [MissingImplInMemberAccessNote] +// CHECK:STDERR: var test_bool: bool = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +var test_bool: bool = (); + +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `()` to `char` [ConversionFailure] +// CHECK:STDERR: var test_char: char = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+4]]:1: note: type `()` does not implement interface `Core.ImplicitAs(char)` [MissingImplInMemberAccessNote] +// CHECK:STDERR: var test_char: char = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +var test_char: char = (); + +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `()` to `str` [ConversionFailure] +// CHECK:STDERR: var test_str: str = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_stringify_type_literals.carbon:[[@LINE+4]]:1: note: type `()` does not implement interface `Core.ImplicitAs(str)` [MissingImplInMemberAccessNote] +// CHECK:STDERR: var test_str: str = (); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +var test_str: str = (); + // CHECK:STDOUT: --- iN.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -390,19 +458,59 @@ var x: type = 42; // CHECK:STDOUT: %test_f128: ref %f128.b8c = bind_name test_f128, %test_f128.var [concrete = %test_f128.var] // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- char.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %char: type = class_type @Char [concrete] +// CHECK:STDOUT: %pattern_type.b09: type = pattern_type %char [concrete] +// CHECK:STDOUT: %.b9b: Core.CharLiteral = char_value U+0063 [concrete] +// CHECK:STDOUT: %ImplicitAs.type.3be: type = facet_type <@ImplicitAs, @ImplicitAs(%char)> [concrete] +// CHECK:STDOUT: %ImplicitAs.Convert.type.f57: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%char) [concrete] +// CHECK:STDOUT: %ImplicitAs.impl_witness: = impl_witness imports.%ImplicitAs.impl_witness_table [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.3be = facet_value Core.CharLiteral, (%ImplicitAs.impl_witness) [concrete] +// CHECK:STDOUT: %.8d6: type = fn_type_with_self_type %ImplicitAs.Convert.type.f57, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.CharLiteral.as.ImplicitAs.impl.Convert.type: type = fn_type @Core.CharLiteral.as.ImplicitAs.impl.Convert [concrete] +// CHECK:STDOUT: %Core.CharLiteral.as.ImplicitAs.impl.Convert: %Core.CharLiteral.as.ImplicitAs.impl.Convert.type = struct_value () [concrete] +// CHECK:STDOUT: %Core.CharLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %.b9b, %Core.CharLiteral.as.ImplicitAs.impl.Convert [concrete] +// CHECK:STDOUT: %int_99: %char = int_value 99 [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core.import_ref.543: %Core.CharLiteral.as.ImplicitAs.impl.Convert.type = import_ref Core//prelude/parts/char, loc13_36, loaded [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.543), @Core.CharLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %test_char.patt: %pattern_type.b09 = binding_pattern test_char [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %impl.elem0: %.8d6 = impl_witness_access constants.%ImplicitAs.impl_witness, element0 [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert] +// CHECK:STDOUT: %bound_method: = bound_method @__global_init.%.loc5, %impl.elem0 [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %Core.CharLiteral.as.ImplicitAs.impl.Convert.call: init %char = call %bound_method(@__global_init.%.loc5) [concrete = constants.%int_99] +// CHECK:STDOUT: %.loc5_23.1: %char = value_of_initializer %Core.CharLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_99] +// CHECK:STDOUT: %.loc5_23.2: %char = converted @__global_init.%.loc5, %.loc5_23.1 [concrete = constants.%int_99] +// CHECK:STDOUT: %test_char: %char = bind_name test_char, %.loc5_23.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc5: Core.CharLiteral = char_value U+0063 [concrete = constants.%.b9b] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- string.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %String: type = class_type @String [concrete] +// CHECK:STDOUT: %str.ee0: type = class_type @String [concrete] // CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete] // CHECK:STDOUT: %u64: type = class_type @UInt, @UInt(%int_64) [concrete] // CHECK:STDOUT: %int_8: Core.IntLiteral = int_value 8 [concrete] // CHECK:STDOUT: %u8: type = class_type @UInt, @UInt(%int_8) [concrete] // CHECK:STDOUT: %ptr.3e8: type = ptr_type %u8 [concrete] -// CHECK:STDOUT: %pattern_type.461: type = pattern_type %String [concrete] -// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "Test" [concrete] +// CHECK:STDOUT: %pattern_type.461: type = pattern_type %str.ee0 [concrete] +// CHECK:STDOUT: %str.c1c: %ptr.3e8 = string_literal "Test" [concrete] // CHECK:STDOUT: %int_4: %u64 = int_value 4 [concrete] -// CHECK:STDOUT: %String.val: %String = struct_value (%str, %int_4) [concrete] +// CHECK:STDOUT: %String.val: %str.ee0 = struct_value (%str.c1c, %int_4) [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -412,14 +520,14 @@ var x: type = 42; // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %test_str.patt: %pattern_type.461 = binding_pattern test_str [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %test_str: %String = bind_name test_str, @__global_init.%String.val +// CHECK:STDOUT: %test_str: %str.ee0 = bind_name test_str, @__global_init.%String.val // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "Test" [concrete = constants.%str] +// CHECK:STDOUT: %str: %ptr.3e8 = string_literal "Test" [concrete = constants.%str.c1c] // CHECK:STDOUT: %int_4: %u64 = int_value 4 [concrete = constants.%int_4] -// CHECK:STDOUT: %String.val: %String = struct_value (%str, %int_4) [concrete = constants.%String.val] +// CHECK:STDOUT: %String.val: %str.ee0 = struct_value (%str, %int_4) [concrete = constants.%String.val] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/lex/testdata/basic_syntax.carbon b/toolchain/lex/testdata/basic_syntax.carbon index b01eea735546..801a4f4375bc 100644 --- a/toolchain/lex/testdata/basic_syntax.carbon +++ b/toolchain/lex/testdata/basic_syntax.carbon @@ -12,21 +12,21 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lex/testdata/basic_syntax.carbon // CHECK:STDOUT: - filename: basic_syntax.carbon // CHECK:STDOUT: tokens: -// CHECK:STDOUT: - { index: 0, kind: "FileStart", line: {{ *\d+}}, column: 1, indent: 1, spelling: "" } +// CHECK:STDOUT: - { index: 0, kind: "FileStart", line: {{ *\d+}}, column: 1, indent: 1, spelling: "" } fn run(str program) { -// CHECK:STDOUT: - { index: 1, kind: "Fn", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "fn", has_leading_space: true } -// CHECK:STDOUT: - { index: 2, kind: "Identifier", line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: "run", identifier: 0, has_leading_space: true } -// CHECK:STDOUT: - { index: 3, kind: "OpenParen", line: {{ *}}[[@LINE-3]], column: 7, indent: 1, spelling: "(", closing_token: 6 } -// CHECK:STDOUT: - { index: 4, kind: "StringTypeLiteral", line: {{ *}}[[@LINE-4]], column: 8, indent: 1, spelling: "str" } -// CHECK:STDOUT: - { index: 5, kind: "Identifier", line: {{ *}}[[@LINE-5]], column: 12, indent: 1, spelling: "program", identifier: 1, has_leading_space: true } -// CHECK:STDOUT: - { index: 6, kind: "CloseParen", line: {{ *}}[[@LINE-6]], column: 19, indent: 1, spelling: ")", opening_token: 3 } -// CHECK:STDOUT: - { index: 7, kind: "OpenCurlyBrace", line: {{ *}}[[@LINE-7]], column: 21, indent: 1, spelling: "{", closing_token: 11, has_leading_space: true } +// CHECK:STDOUT: - { index: 1, kind: "Fn", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "fn", has_leading_space: true } +// CHECK:STDOUT: - { index: 2, kind: "Identifier", line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: "run", identifier: 0, has_leading_space: true } +// CHECK:STDOUT: - { index: 3, kind: "OpenParen", line: {{ *}}[[@LINE-3]], column: 7, indent: 1, spelling: "(", closing_token: 6 } +// CHECK:STDOUT: - { index: 4, kind: "Str", line: {{ *}}[[@LINE-4]], column: 8, indent: 1, spelling: "str" } +// CHECK:STDOUT: - { index: 5, kind: "Identifier", line: {{ *}}[[@LINE-5]], column: 12, indent: 1, spelling: "program", identifier: 1, has_leading_space: true } +// CHECK:STDOUT: - { index: 6, kind: "CloseParen", line: {{ *}}[[@LINE-6]], column: 19, indent: 1, spelling: ")", opening_token: 3 } +// CHECK:STDOUT: - { index: 7, kind: "OpenCurlyBrace", line: {{ *}}[[@LINE-7]], column: 21, indent: 1, spelling: "{", closing_token: 11, has_leading_space: true } return True; - // CHECK:STDOUT: - { index: 8, kind: "Return", line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: "return", has_leading_space: true } - // CHECK:STDOUT: - { index: 9, kind: "Identifier", line: {{ *}}[[@LINE-2]], column: 10, indent: 3, spelling: "True", identifier: 2, has_leading_space: true } - // CHECK:STDOUT: - { index: 10, kind: "Semi", line: {{ *}}[[@LINE-3]], column: 14, indent: 3, spelling: ";" } + // CHECK:STDOUT: - { index: 8, kind: "Return", line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: "return", has_leading_space: true } + // CHECK:STDOUT: - { index: 9, kind: "Identifier", line: {{ *}}[[@LINE-2]], column: 10, indent: 3, spelling: "True", identifier: 2, has_leading_space: true } + // CHECK:STDOUT: - { index: 10, kind: "Semi", line: {{ *}}[[@LINE-3]], column: 14, indent: 3, spelling: ";" } } -// CHECK:STDOUT: - { index: 11, kind: "CloseCurlyBrace", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "}", opening_token: 7, has_leading_space: true } +// CHECK:STDOUT: - { index: 11, kind: "CloseCurlyBrace", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "}", opening_token: 7, has_leading_space: true } -// CHECK:STDOUT: - { index: 12, kind: "FileEnd", line: {{ *}}[[@LINE+0]], column: {{ *\d+}}, indent: 1, spelling: "", has_leading_space: true } +// CHECK:STDOUT: - { index: 12, kind: "FileEnd", line: {{ *}}[[@LINE+0]], column: {{ *\d+}}, indent: 1, spelling: "", has_leading_space: true } diff --git a/toolchain/lex/testdata/fail_block_string_second_line.carbon b/toolchain/lex/testdata/fail_block_string_second_line.carbon index 07dab5d67c19..2854e4806461 100644 --- a/toolchain/lex/testdata/fail_block_string_second_line.carbon +++ b/toolchain/lex/testdata/fail_block_string_second_line.carbon @@ -19,9 +19,9 @@ var s: str = ''' // CHECK:STDERR: // CHECK:STDOUT: - filename: fail_block_string_second_line.carbon // CHECK:STDOUT: tokens: -// CHECK:STDOUT: - { index: 1, kind: "Var", line: {{ *}}[[@LINE-17]], column: 1, indent: 1, spelling: "var", has_leading_space: true } -// CHECK:STDOUT: - { index: 2, kind: "Identifier", line: {{ *}}[[@LINE-18]], column: 5, indent: 1, spelling: "s", identifier: 0, has_leading_space: true } -// CHECK:STDOUT: - { index: 3, kind: "Colon", line: {{ *}}[[@LINE-19]], column: 6, indent: 1, spelling: ":" } -// CHECK:STDOUT: - { index: 4, kind: "StringTypeLiteral", line: {{ *}}[[@LINE-20]], column: 8, indent: 1, spelling: "str", has_leading_space: true } -// CHECK:STDOUT: - { index: 5, kind: "Equal", line: {{ *}}[[@LINE-21]], column: 12, indent: 1, spelling: "=", has_leading_space: true } -// CHECK:STDOUT: - { index: 6, kind: "StringLiteral", line: {{ *}}[[@LINE-22]], column: 14, indent: 1, spelling: "'''\n error here: '''", value: "error here: ", has_leading_space: true } +// CHECK:STDOUT: - { index: 1, kind: "Var", line: {{ *}}[[@LINE-17]], column: 1, indent: 1, spelling: "var", has_leading_space: true } +// CHECK:STDOUT: - { index: 2, kind: "Identifier", line: {{ *}}[[@LINE-18]], column: 5, indent: 1, spelling: "s", identifier: 0, has_leading_space: true } +// CHECK:STDOUT: - { index: 3, kind: "Colon", line: {{ *}}[[@LINE-19]], column: 6, indent: 1, spelling: ":" } +// CHECK:STDOUT: - { index: 4, kind: "Str", line: {{ *}}[[@LINE-20]], column: 8, indent: 1, spelling: "str", has_leading_space: true } +// CHECK:STDOUT: - { index: 5, kind: "Equal", line: {{ *}}[[@LINE-21]], column: 12, indent: 1, spelling: "=", has_leading_space: true } +// CHECK:STDOUT: - { index: 6, kind: "StringLiteral", line: {{ *}}[[@LINE-22]], column: 14, indent: 1, spelling: "'''\n error here: '''", value: "error here: ", has_leading_space: true } diff --git a/toolchain/lex/token_kind.def b/toolchain/lex/token_kind.def index 5cd423e39900..6a37779388df 100644 --- a/toolchain/lex/token_kind.def +++ b/toolchain/lex/token_kind.def @@ -176,6 +176,7 @@ CARBON_KEYWORD_TOKEN(Auto, "auto") CARBON_KEYWORD_TOKEN(Bool, "bool") CARBON_KEYWORD_TOKEN(Break, "break") CARBON_KEYWORD_TOKEN(Case, "case") +CARBON_KEYWORD_TOKEN(Char, "char") CARBON_KEYWORD_TOKEN(Const, "const") CARBON_KEYWORD_TOKEN(Continue, "continue") CARBON_KEYWORD_TOKEN(Core, "Core") @@ -209,7 +210,7 @@ CARBON_KEYWORD_TOKEN(Returned, "returned") CARBON_KEYWORD_TOKEN(SelfTypeIdentifier, "Self") CARBON_KEYWORD_TOKEN(SelfValueIdentifier, "self") // TODO: Although we provide a `str` type literal, it's not standardized. -CARBON_KEYWORD_TOKEN(StringTypeLiteral, "str") +CARBON_KEYWORD_TOKEN(Str, "str") CARBON_KEYWORD_TOKEN(Template, "template") CARBON_KEYWORD_TOKEN(Then, "then") CARBON_KEYWORD_TOKEN(True, "true") diff --git a/toolchain/parse/handle_expr.cpp b/toolchain/parse/handle_expr.cpp index f0455f7aae8f..035d3789329d 100644 --- a/toolchain/parse/handle_expr.cpp +++ b/toolchain/parse/handle_expr.cpp @@ -114,6 +114,11 @@ auto HandleExprInPostfix(Context& context) -> void { context.PushState(state); break; } + case Lex::TokenKind::Char: { + context.AddLeafNode(NodeKind::CharTypeLiteral, context.Consume()); + context.PushState(state); + break; + } case Lex::TokenKind::IntTypeLiteral: { context.AddLeafNode(NodeKind::IntTypeLiteral, context.Consume()); context.PushState(state); @@ -129,7 +134,7 @@ auto HandleExprInPostfix(Context& context) -> void { context.PushState(state); break; } - case Lex::TokenKind::StringTypeLiteral: { + case Lex::TokenKind::Str: { context.AddLeafNode(NodeKind::StringTypeLiteral, context.Consume()); context.PushState(state); break; diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index de29180ac512..68520bab022a 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -251,14 +251,15 @@ CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(CharLiteral, CharLiteral) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(RealLiteral, RealLiteral) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(StringLiteral, StringLiteral) +CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(AutoTypeLiteral, Auto) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(BoolTypeLiteral, Bool) +CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(CharTypeLiteral, Char) +CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(FloatTypeLiteral, FloatTypeLiteral) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(IntTypeLiteral, IntTypeLiteral) +CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(StringTypeLiteral, Str) +CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(TypeTypeLiteral, Type) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(UnsignedIntTypeLiteral, UnsignedIntTypeLiteral) -CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(FloatTypeLiteral, FloatTypeLiteral) -CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(StringTypeLiteral, StringTypeLiteral) -CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(TypeTypeLiteral, Type) -CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(AutoTypeLiteral, Auto) CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Amp) CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Caret) diff --git a/toolchain/parse/testdata/basics/type_literals.carbon b/toolchain/parse/testdata/basics/type_literals.carbon index 29cf41d2bcc8..95fe887cbb86 100644 --- a/toolchain/parse/testdata/basics/type_literals.carbon +++ b/toolchain/parse/testdata/basics/type_literals.carbon @@ -10,6 +10,7 @@ var test_i32: i32 = 0; var test_f64: f64 = 0.1; +var test_char: char = 'c'; var test_str: str = "Test"; // CHECK:STDOUT: - filename: type_literals.carbon @@ -32,6 +33,14 @@ var test_str: str = "Test"; // CHECK:STDOUT: {kind: 'RealLiteral', text: '0.1'}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 8}, // CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'}, +// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'test_char'}, +// CHECK:STDOUT: {kind: 'CharTypeLiteral', text: 'char'}, +// CHECK:STDOUT: {kind: 'VarBindingPattern', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'VariablePattern', text: 'var', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, +// CHECK:STDOUT: {kind: 'CharLiteral', text: ''c''}, +// CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 8}, +// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'}, // CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'test_str'}, // CHECK:STDOUT: {kind: 'StringTypeLiteral', text: 'str'}, // CHECK:STDOUT: {kind: 'VarBindingPattern', text: ':', subtree_size: 3}, diff --git a/toolchain/sem_ir/inst_namer.cpp b/toolchain/sem_ir/inst_namer.cpp index d18391ac8cb6..8a66d783050b 100644 --- a/toolchain/sem_ir/inst_namer.cpp +++ b/toolchain/sem_ir/inst_namer.cpp @@ -774,7 +774,7 @@ auto InstNamer::NamingContext::NameInst() -> void { return; } case CARBON_KIND(ClassType inst): { - if (auto literal_info = NumericTypeLiteralInfo::ForType(sem_ir(), inst); + if (auto literal_info = TypeLiteralInfo::ForType(sem_ir(), inst); literal_info.is_valid()) { AddInstName(literal_info.GetLiteralAsString(sem_ir())); } else { diff --git a/toolchain/sem_ir/name_scope.h b/toolchain/sem_ir/name_scope.h index 29d62454d754..ad7507f4c534 100644 --- a/toolchain/sem_ir/name_scope.h +++ b/toolchain/sem_ir/name_scope.h @@ -355,6 +355,13 @@ class NameScopeStore { // Returns whether the provided scope ID is for the Core package. auto IsCorePackage(NameScopeId scope_id) const -> bool; + // Returns whether the provided scope ID is valid and is directly contained + // within the Core package. + auto IsInCorePackage(NameScopeId scope_id) const -> bool { + return scope_id.has_value() && + IsCorePackage(Get(scope_id).parent_scope_id()); + } + auto OutputYaml() const -> Yaml::OutputMapping { return values_.OutputYaml(); } diff --git a/toolchain/sem_ir/stringify.cpp b/toolchain/sem_ir/stringify.cpp index 5918eed4a9bb..9e59d5516c5a 100644 --- a/toolchain/sem_ir/stringify.cpp +++ b/toolchain/sem_ir/stringify.cpp @@ -288,7 +288,7 @@ class Stringifier { auto StringifyInst(InstId /*inst_id*/, ClassType inst) -> void { const auto& class_info = sem_ir_->classes().Get(inst.class_id); - if (auto literal_info = NumericTypeLiteralInfo::ForType(*sem_ir_, inst); + if (auto literal_info = TypeLiteralInfo::ForType(*sem_ir_, inst); literal_info.is_valid()) { literal_info.PrintLiteral(*sem_ir_, *out_); return; @@ -751,7 +751,7 @@ auto StringifySpecific(const File& sem_ir, SpecificId specific_id) // Print `Core.Int(N)` as `iN`. // TODO: This duplicates work done in StringifyInst for ClassType. const auto& class_info = sem_ir.classes().Get(class_decl.class_id); - if (auto literal_info = NumericTypeLiteralInfo::ForType( + if (auto literal_info = TypeLiteralInfo::ForType( sem_ir, ClassType{.type_id = TypeType::TypeId, .class_id = class_decl.class_id, .specific_id = specific_id}); diff --git a/toolchain/sem_ir/type_info.cpp b/toolchain/sem_ir/type_info.cpp index e91348aa7a83..6b2cb82f00a2 100644 --- a/toolchain/sem_ir/type_info.cpp +++ b/toolchain/sem_ir/type_info.cpp @@ -85,9 +85,7 @@ auto NumericTypeLiteralInfo::ForType(const File& file, ClassType class_type) // The class must be declared in the `Core` package. const auto& class_info = file.classes().Get(class_type.class_id); - if (!class_info.scope_id.has_value() || - !file.name_scopes().IsCorePackage( - file.name_scopes().Get(class_info.scope_id).parent_scope_id())) { + if (!file.name_scopes().IsInCorePackage(class_info.scope_id)) { return NumericTypeLiteralInfo::Invalid; } @@ -135,4 +133,58 @@ auto NumericTypeLiteralInfo::GetLiteralAsString(const File& file) const return out.TakeStr(); } +auto TypeLiteralInfo::ForType(const File& file, ClassType class_type) + -> TypeLiteralInfo { + if (class_type.specific_id.has_value()) { + auto numeric = NumericTypeLiteralInfo::ForType(file, class_type); + if (numeric.is_valid()) { + return {.kind = Numeric, .numeric = numeric}; + } + return {.kind = None}; + } + + // The class must be declared in the `Core` package. + const auto& class_info = file.classes().Get(class_type.class_id); + if (!file.name_scopes().IsInCorePackage(class_info.scope_id)) { + return {.kind = None}; + } + + // The class's name must be the name corresponding to a type literal. + auto name_ident = file.names().GetAsStringIfIdentifier(class_info.name_id); + if (!name_ident) { + return {.kind = None}; + } + + Kind kind = llvm::StringSwitch(*name_ident) + .Case("Char", Char) + .Case("String", Str) + .Default(None); + return {.kind = kind}; +} + +auto TypeLiteralInfo::PrintLiteral(const File& file, + llvm::raw_ostream& out) const -> void { + CARBON_CHECK(is_valid()); + switch (kind) { + case None: + CARBON_FATAL("Printing invalid type literal"); + case Numeric: + numeric.PrintLiteral(file, out); + break; + case Char: + out << "char"; + break; + case Str: + out << "str"; + break; + } +} + +auto TypeLiteralInfo::GetLiteralAsString(const File& file) const + -> std::string { + RawStringOstream out; + PrintLiteral(file, out); + return out.TakeStr(); +} + } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/type_info.h b/toolchain/sem_ir/type_info.h index 7be3a2a5e814..fd767cf5cd7d 100644 --- a/toolchain/sem_ir/type_info.h +++ b/toolchain/sem_ir/type_info.h @@ -227,6 +227,38 @@ struct NumericTypeLiteralInfo { IntId bit_width_id; }; +// Information about a literal that corresponds to a type. +struct TypeLiteralInfo { + enum Kind : char { + None, + // A numeric type literal such as `i8`; see `numeric` field for details. + Numeric, + // `char` / `Core.Char`. + Char, + // `str` / `Core.String`. + // TODO: Rename `Core.String` to `Core.Str`. + Str, + }; + + // Returns the type literal that would evaluate to this class type, if any. + static auto ForType(const File& file, ClassType class_type) + -> TypeLiteralInfo; + + // Prints the type literal that corresponds to this type. + auto PrintLiteral(const File& file, llvm::raw_ostream& out) const -> void; + + // Gets a string containing the literal. + auto GetLiteralAsString(const File& file) const -> std::string; + + // Returns whether this is a valid type literal. + auto is_valid() const -> bool { return kind != None; } + + // The kind of the literal. + Kind kind; + // If this is a numeric literal, additional information about the literal. + NumericTypeLiteralInfo numeric = NumericTypeLiteralInfo::Invalid; +}; + inline constexpr NumericTypeLiteralInfo NumericTypeLiteralInfo::Invalid = { .kind = None, .bit_width_id = IntId::None}; diff --git a/toolchain/testing/testdata/min_prelude/parts/char.carbon b/toolchain/testing/testdata/min_prelude/parts/char.carbon new file mode 100644 index 000000000000..9b18edaed281 --- /dev/null +++ b/toolchain/testing/testdata/min_prelude/parts/char.carbon @@ -0,0 +1,21 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/uint.carbon + +// --- min_prelude/parts/char.carbon + +package Core library "prelude/parts/char"; + +import library "prelude/parts/uint"; + +fn CharLiteral() -> type = "char_literal.make_type"; + +class Char { + adapt u8; +} + +impl CharLiteral() as ImplicitAs(Char) { + fn Convert[self: Self]() -> Char = "char.convert_checked"; +} diff --git a/toolchain/testing/testdata/min_prelude/primitives.carbon b/toolchain/testing/testdata/min_prelude/primitives.carbon index bccc42a4ac4f..a36e4a9153be 100644 --- a/toolchain/testing/testdata/min_prelude/primitives.carbon +++ b/toolchain/testing/testdata/min_prelude/primitives.carbon @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/bool.carbon +// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/char.carbon // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/copy.carbon // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/float.carbon // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/int.carbon @@ -16,6 +17,7 @@ package Core library "prelude"; export import library "prelude/parts/bool"; +export import library "prelude/parts/char"; export import library "prelude/parts/copy"; export import library "prelude/parts/float"; export import library "prelude/parts/int";