Skip to content

Conversation

@viniciusfdasilva
Copy link

@viniciusfdasilva viniciusfdasilva commented Nov 24, 2025

This pull request adds support for integer-to-char conversion, allowing the compiler to correctly handle character casting, implementing part of the issue #5922.

import Core library "io";

fn Run() -> i32 {
	var i : i32 = 65;
	var ch: char = (i as char); // Support implemented!
	Core.PrintChar(ch); // Print 'A'
	return 0;
}

@viniciusfdasilva viniciusfdasilva requested a review from a team as a code owner November 24, 2025 11:40
@viniciusfdasilva viniciusfdasilva requested review from danakj and removed request for a team November 24, 2025 11:40
@google-cla

This comment was marked as outdated.

@danakj
Copy link
Contributor

danakj commented Nov 24, 2025

This pull request adds support for i32-to-char conversion, enabling the compiler to correctly handle character casting from 32-bit integers.

import Core library "io";

fn Run() -> i32 {
	var i : i32 = 65;
	var ch: char = (i as char); // Support implemented!
	Core.PrintChar(ch); // Print 'A'
	return 0;
}

I don't see i32 -> char listed in here as a builtin operation: #5922 (comment)

Could you clarify where in the design or a proposal or leads issue this is from?

@danakj
Copy link
Contributor

danakj commented Nov 24, 2025

This pull request adds support for i32-to-char conversion, enabling the compiler to correctly handle character casting from 32-bit integers.

import Core library "io";

fn Run() -> i32 {
	var i : i32 = 65;
	var ch: char = (i as char); // Support implemented!
	Core.PrintChar(ch); // Print 'A'
	return 0;
}

I don't see i32 -> char listed in here as a builtin operation: #5922 (comment)

Could you clarify where in the design or a proposal or leads issue this is from?

Oh I see it:

Explicit conversion to/from integers equivalent to what u8 supports.
Continuing no implicit conversions.

Could you add a link to the PR description?

Copy link
Contributor

@danakj danakj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add tests including both tests that now pass and tests that fail for bad values or types, and tests that pass/fail for making a "convert_char" builtin signature that is correct or malformed.

fn Convert[self: Self]() -> Char = "char.convert_checked";
}

impl Int(32) as As(Char) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this generic for all integer sizes, like it is for u8?

final impl forall [From:! IntLiteral(), To:! IntLiteral()] UInt(From) as As(UInt(To)) {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @danakj

I had issues with this kind of implementation, but I managed to get support working for i32, i8, and i64! However, I’ll work on adapting it to what you suggested in the future.

Comment on lines 870 to 877
for (const auto& constraint : info.extend_named_constraints) {
ResolveSpecificDeclForSpecificId(eval_context,
constraint.specific_id);
}
for (const auto& constraint : info.self_impls_named_constraints) {
ResolveSpecificDeclForSpecificId(eval_context,
constraint.specific_id);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a bad rebase?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a branch update problem!
I'll fix that as well!
This code should be included.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this snippet again!

Comment on lines 1031 to 1033
//// Performs a conversion from integer to character type.
// Performs a conversion between character types, diagnosing if the value
// doesn't fit in the destination type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a copy paste that needs to be cleaned up?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!! I will remove this

// Performs a conversion between character types, diagnosing if the value
// doesn't fit in the destination type.
static auto PerformCharConvert(Context& context, SemIR::LocId loc_id,
SemIR::InstId arg_id,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest setting up pre-commit locally so things like formatting are fixed before uploading. https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/contribution_tools.md

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I used pre-commit in my new submition :)

Comment on lines 1057 to 1058
// Values over 0x80 require multiple code units in UTF-8.
if (value >= 0x80) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This surprised me, could you point me to where the design says this should happen, rather than converting anything up to 255?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it’s a restriction I initially included, but it may indeed not make sense to keep it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! I removed this code snippet! I don’t think it makes sense to add this check.

constexpr BuiltinInfo ReadChar = {"read.char",
ValidateSignature<auto()->AnySizedInt>};


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment on lines 32 to 33
fn Convert[self: Self]() -> Char = "int.convert_char";
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change
fn Convert[self: Self]() -> Char = "int.convert_char";
}
fn Convert[self: Self]() -> Char = "int.convert_char";
}

SemIR::InstId arg_id,
SemIR::TypeId dest_type_id)
-> SemIR::ConstantId {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change

Comment on lines 1035 to 1036
SemIR::InstId arg_id,
SemIR::TypeId dest_type_id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change
SemIR::InstId arg_id,
SemIR::TypeId dest_type_id)
SemIR::InstId arg_id, SemIR::TypeId dest_type_id)

SemIR::InstId arg_id,
SemIR::TypeId dest_type_id)
-> SemIR::ConstantId {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change


auto [is_signed, bit_width_id] =
context.sem_ir().types().GetIntTypeInfo(dest_type_id);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change

{.type = arg.type_id, .value = arg_val},
dest_type_id);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change

Comment on lines 1059 to 1062
CARBON_DIAGNOSTIC(
NegativeIntInUnsignedType, Error,
"character value {0} too large for type {1}", TypedInt,
SemIR::TypeId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change
CARBON_DIAGNOSTIC(
NegativeIntInUnsignedType, Error,
"character value {0} too large for type {1}", TypedInt,
SemIR::TypeId);
CARBON_DIAGNOSTIC(NegativeIntInUnsignedType, Error,
"character value {0} too large for type {1}", TypedInt,
SemIR::TypeId);


// Integer conversions.
case SemIR::BuiltinFunctionKind::IntConvertChar: {
if (phase != Phase::Concrete) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change
if (phase != Phase::Concrete) {
if (phase != Phase::Concrete) {

constexpr BuiltinInfo ReadChar = {"read.char",
ValidateSignature<auto()->AnySizedInt>};


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change

Comment on lines 416 to 417
constexpr BuiltinInfo IntConvertChar = {"int.convert_char",
ValidateSignature<auto(AnyInt)->CharCompatible>};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[diff] reported by reviewdog 🐶

Suggested change
constexpr BuiltinInfo IntConvertChar = {"int.convert_char",
ValidateSignature<auto(AnyInt)->CharCompatible>};
constexpr BuiltinInfo IntConvertChar = {
"int.convert_char", ValidateSignature<auto(AnyInt)->CharCompatible>};

@viniciusfdasilva viniciusfdasilva changed the title Adding support for i32-to-char conversion Adding support for i32, i8 and i64 to-char conversion Nov 26, 2025
@viniciusfdasilva viniciusfdasilva changed the title Adding support for i32, i8 and i64 to-char conversion Adding support for i32, i8 and i64 to-char conversion Nov 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants