Add support for char keyword per #5903. (#6078)

Make inst namer and stringify print `Core.Char` and `Core.String` as
`char` and `str` respectively. Plus a few cleanups.
This commit is contained in:
Richard Smith
2025-09-16 20:45:01 +00:00
committed by GitHub
parent 59c4cbcaf1
commit bac828d244
21 changed files with 351 additions and 106 deletions
+7
View File
@@ -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,
@@ -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:
@@ -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: <witness> = 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> = 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: <witness> = 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> = 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> = 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> = 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> = 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> = 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> = bound_method %.loc8_11.5, constants.%Char.as.Destroy.impl.Op
// CHECK:STDOUT: %char.as.Destroy.impl.Op.bound: <bound method> = 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: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -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:
@@ -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: <namespace> = 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: <namespace> = 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:
+17 -17
View File
@@ -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: <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: <witness> = 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> = 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> = 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> = 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> = 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
+13 -13
View File
@@ -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: <elided>
// 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, <error> [concrete = <error>]
// CHECK:STDOUT: %x: %str.ee0 = bind_name x, <error> [concrete = <error>]
// 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: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+115 -7
View File
@@ -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: <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> = 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> = 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: <elided>
// 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: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+13 -13
View File
@@ -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 }
@@ -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 }
+2 -1
View File
@@ -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")
+6 -1
View File
@@ -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;
+5 -4
View File
@@ -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)
+9
View File
@@ -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},
+1 -1
View File
@@ -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 {
+7
View File
@@ -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();
}
+2 -2
View File
@@ -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});
+55 -3
View File
@@ -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<Kind>(*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
+32
View File
@@ -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};
@@ -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";
}
@@ -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";