Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions core/prelude/types/char.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ impl CharLiteral() as ImplicitAs(Char) {
impl CharLiteral() as As(Char) {
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.

Copy link
Contributor

Choose a reason for hiding this comment

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

Could you say more what issues you had? I think we should be able to write this as a single generic.

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";
}

57 changes: 49 additions & 8 deletions toolchain/check/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -867,14 +867,6 @@ static auto ResolveSpecificDeclForInst(EvalContext& eval_context,
for (const auto& interface : info.self_impls_constraints) {
ResolveSpecificDeclForSpecificId(eval_context, interface.specific_id);
}
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);
}
break;
}
case CARBON_KIND(SemIR::SpecificId specific_id): {
Expand Down Expand Up @@ -991,6 +983,7 @@ static auto PerformCheckedCharConvert(Context& context, SemIR::LocId loc_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 arg = context.insts().GetAs<SemIR::CharLiteralValue>(arg_id);

// Values over 0x80 require multiple code units in UTF-8.
Expand Down Expand Up @@ -1035,6 +1028,48 @@ static auto MakeFloatTypeResult(Context& context, SemIR::LocId loc_id,
return MakeConstantResult(context, result, phase);
}

//// 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

static auto PerformCharConvert(Context& context, SemIR::LocId loc_id,
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::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 arg = context.insts().GetAs<SemIR::IntValue>(arg_id);
auto arg_val = context.ints().Get(arg.int_id);

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

if (!is_signed && arg_val.isNegative()) {
CARBON_DIAGNOSTIC(
NegativeIntInUnsignedType, Error,
"negative integer value {0} converted to unsigned type {1}", TypedInt,
SemIR::TypeId);
context.emitter().Emit(loc_id, NegativeIntInUnsignedType,
{.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

int64_t value = arg_val.getSExtValue();

// 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.

CARBON_DIAGNOSTIC(
NegativeIntInUnsignedType, Error,
"character value {0} too large for type {1}", TypedInt,
SemIR::TypeId);
Comment on lines 1052 to 1055
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);

context.emitter().Emit(loc_id, NegativeIntInUnsignedType,
{.type = arg.type_id, .value = arg_val},
dest_type_id);
return SemIR::ErrorInst::ConstantId;
}

llvm::APInt int_val(8, value, /*isSigned=*/false);
return MakeIntResult(context, dest_type_id, /*is_signed=*/false, int_val);
}

// Performs a conversion between integer types, truncating if the value doesn't
// fit in the destination type.
static auto PerformIntConvert(Context& context, SemIR::InstId arg_id,
Expand Down Expand Up @@ -1820,6 +1855,12 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context,
}

// 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) {

return MakeConstantResult(context, call, phase);
}
return PerformCharConvert(context, loc_id, arg_ids[0], call.type_id);
}
case SemIR::BuiltinFunctionKind::IntConvert: {
if (phase != Phase::Concrete) {
return MakeConstantResult(context, call, phase);
Expand Down
1 change: 1 addition & 0 deletions toolchain/lower/handle_call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
context.SetLocal(inst_id, context.GetTypeAsValue());
return;

case SemIR::BuiltinFunctionKind::IntConvertChar:
case SemIR::BuiltinFunctionKind::IntConvert: {
context.SetLocal(inst_id,
CreateExtOrTrunc(context, context.GetValue(arg_ids[0]),
Expand Down
6 changes: 6 additions & 0 deletions toolchain/sem_ir/builtin_function_kind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ constexpr BuiltinInfo PrintInt = {
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

// Returns the `Core.CharLiteral` type.
constexpr BuiltinInfo CharLiteralMakeType = {"char_literal.make_type",
ValidateSignature<auto()->Type>};
Expand Down Expand Up @@ -411,6 +412,10 @@ constexpr BuiltinInfo CharConvertChecked = {
"char.convert_checked",
ValidateSignature<auto(CharLiteral)->CharCompatible>};

// Converts from an integer type to a char-compatible type (u8/adapted Char).
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>};


// Converts between integer types, truncating if necessary.
constexpr BuiltinInfo IntConvert = {"int.convert",
ValidateSignature<auto(AnyInt)->AnyInt>};
Expand Down Expand Up @@ -784,6 +789,7 @@ auto BuiltinFunctionKind::IsCompTimeOnly(const File& sem_ir,
// Checked conversions are compile-time only.
return true;

case IntConvertChar:
case IntConvert:
case IntSNegate:
case IntComplement:
Expand Down
1 change: 1 addition & 0 deletions toolchain/sem_ir/builtin_function_kind.def
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(MaybeUnformedMakeType)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(CharConvertChecked)

// Integer conversion.
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntConvertChar)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntConvert)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntConvertChecked)

Expand Down
Loading